#include "colaborative_conf.h"
#include "ui_colaborative_conf.h"
#include "touchexmppclient.h"
#include "QXmppLogger.h"
#include "QFile"
#include "stdlib.h"
#include "QXmppConfiguration.h"
#include "interpreter.h"
#include "channel.h"
#include <QInputDialog>
#include <QMessageBox>
#include <QTreeWidgetItem>
#include <QTabWidget>
#include "writer.h"
using namespace Touche;

ColaborationWindow::ColaborationWindow(Touche::ColaborativeManager *manager, QWidget *parent):
    QTabWidget(parent),
    ui(new Ui::ColaborationWindow),
    m_manager(manager)
{
    ui->setupUi(this);
    this->setCurrentWidget(this->ui->t_inicial);
    connected = false;
    connect(this->m_manager, SIGNAL(contactsChanged()), this, SLOT(contactsChanged()));
    connect(this->m_manager, SIGNAL(channelsChanged()), this, SLOT(channelsChanged()));
    connect(this,SIGNAL(newBuddyRequest(QString)),this->m_manager,SLOT(addBuddy(QString)));
    connect(this,SIGNAL(buddyRemove(QString)),this->m_manager,SLOT(removeBuddy(QString)));
    connect(this->m_manager, SIGNAL(contactsChanged()), this, SLOT(loadBuddies()));
    connect(this->m_manager, SIGNAL(messageReceived(QXmppMessage)), this, SLOT(on_messageReceived(QXmppMessage)));
    connect(this->m_manager, SIGNAL(connected()),this,SLOT(on_connected()));
}

ColaborationWindow::~ColaborationWindow()
{
    delete ui;
}
void ColaborationWindow::on_connected(){
    ui->l_loginInform->setText("You are logged as");
    ui->l_loginName->setText(m_manager->getLogin());
    connected = true;
}

void ColaborationWindow::onPrivateMessage(const QString &body,const QString &from)
{

    QString bareJid(from);
    bareJid.remove(from.indexOf("/"), from.length());

    if(!buddies.contains(bareJid)){
        QString tabName(from);
        tabName.remove(from.indexOf("@"), from.length());
        TabWidget *newTab = new TabWidget(bareJid, this);
        int row = newTab->historico()->currentRow();
        buddies.insert(bareJid, newTab);
        QTabWidget::addTab(newTab, tabName);
        QTabWidget::setCurrentWidget(newTab);
        newTab->historico()->addItem(bareJid + " wrote: " + body);
        newTab->historico()->setCurrentRow(++row);
        connect(newTab, SIGNAL(privateMessage(QString,QString)), this, SLOT(sendPrivateMessage(QString,QString)));
        connect(newTab, SIGNAL(destroyed(QObject*)), this, SLOT(onTabDeleted(QObject*)));
    }else{
        buddies[bareJid]->historico()->addItem(bareJid + " wrote: " + body);
        int row =  buddies[bareJid]->historico()->currentRow();
        buddies[bareJid]->historico()->setCurrentRow(++row);
    }
}

void ColaborationWindow::onChannelMessage(const QString &body,const QString &from)
{
    QString bareJid(from);
    bareJid.remove(from.indexOf("/"), from.length());
    int row = ui->li_channelChat->currentRow();
    ui->li_channelChat->addItem(bareJid + ": " + body);
    ui->li_channelChat->setCurrentRow(++row);
}

void ColaborationWindow::connectionError(const QXmppMessage)
{
    QMessageBox::information(this,"Could not Connect","Impossible to Connect",QMessageBox::Ok);
}

void ColaborationWindow::loadBuddies()
{
    this->ui->li_contactsList_2->clear();
    this->ui->li_contactsList_2->addItems(m_manager->allBuddies());
}


void ColaborationWindow::updateChannelsView()
{
   ui->channelView->clear();
   QString channelSelected = this->ui->l_channel_name->text();
   bool findChannel = false;
   //update all the channels with new user or new channel in channelview
   foreach(Channel * chan, this->m_manager->channels()){
       QTreeWidgetItem * channel_item = new QTreeWidgetItem(ui->channelView);
        channel_item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
        channel_item-> setText(0, chan->name());
        //ui->channelView->addTopLevelItem(channel_item);
        if (channel_item->text(0) == channelSelected){
            QTreeWidgetItem * user = new QTreeWidgetItem(channel_item);
            user->setFlags(!Qt::ItemIsSelectable);
            user->setText(0,this->m_manager->getLogin());
            findChannel = true;
            //update atual channel
            this->ui->channelView_2->clear();
            QTreeWidgetItem *atual_channel_item = new QTreeWidgetItem(this->ui->channelView_2);
            atual_channel_item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
            atual_channel_item->setText(0,channelSelected);
            //update atual channel with atual login
            QTreeWidgetItem * atualChannel_user = new QTreeWidgetItem(atual_channel_item);
            atualChannel_user->setFlags(!Qt::ItemIsSelectable);
            atualChannel_user->setText(0,this->m_manager->getLogin());
            //update atual channel with others users
            foreach(QString userBareJid, chan->usersBarejid()){
                QTreeWidgetItem * atualChannel_user = new QTreeWidgetItem(atual_channel_item);
                atualChannel_user->setFlags(!Qt::ItemIsSelectable);
                atualChannel_user->setText(0,userBareJid);
            }
            //show the channel in channelview
            ui->channelView_2->addTopLevelItem(atual_channel_item);
        }
        //update the users in all the channels
        foreach(QString userBareJid, chan->usersBarejid()){
            QTreeWidgetItem * users = new QTreeWidgetItem(channel_item);
            users->setFlags(!Qt::ItemIsSelectable);
            users->setText(0,userBareJid);
        }
        //show new channel
        ui->channelView->addTopLevelItem(channel_item);
   }
   //if the variable channel not set true, one new channel was created and here, update channelview
   //and enter in the new channel
   if(!findChannel && !channelSelected.isEmpty()){
       QTreeWidgetItem * channel_item = new QTreeWidgetItem(ui->channelView);
       channel_item->setText(0,channelSelected);
       channel_item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
       this->ui->l_channel_name->setText(channelSelected);
       QTreeWidgetItem * user = new QTreeWidgetItem(channel_item);
       user->setFlags(!Qt::ItemIsSelectable);
       user->setText(0,this->m_manager->getLogin());
       this->ui->channelView->addTopLevelItem(channel_item);
       this->ui->channelView_2->clear();
       QTreeWidgetItem *atualChannel_item = new QTreeWidgetItem(ui->channelView_2);
       atualChannel_item->setText(0,channelSelected);
       QTreeWidgetItem *atualChannel_user = new QTreeWidgetItem(atualChannel_item);
       atualChannel_user->setFlags(!Qt::ItemIsSelectable);
       atualChannel_user->setText(0,this->m_manager->getLogin());
       this->ui->channelView->addTopLevelItem(atualChannel_item);
   }
}

void ColaborationWindow::sendPrivateMessage(const QString &body, const QString &from)
{
    m_manager->sendMessageToUser(from, body);
}

void ColaborationWindow::contactsChanged()
{
    ui->li_ContactsList->clear();
    ui->li_ContactsList->addItems(this->m_manager->contacts());

}

void ColaborationWindow::channelsChanged()
{
    this->updateChannelsView();
}

void ColaborationWindow::on_desconect_button_clicked()
{
    this->m_manager->disconnectAccount();
    this->m_manager->contacts().clear();
    ui->li_ContactsList->clear();
    ui->txt_chatChannel->clear();
    this->m_manager->clearContacts();
    this->m_manager->channels().clear();;
    ui->channelView->clear();
    this->m_manager->clearChannel();
    this->ui->l_channel_name->clear();
    this->close();
    ui->channelView_2->clear();
    ui->li_contactsList_2->clear();
    ui->l_loginInform->setText("You are not logged");
    ui->l_loginName->setText("");
    connected = false;
}

void ColaborationWindow::on_add_buddy_clicked()
{
    if (!ui->edt_addBuddy->text().isEmpty()){
       emit newBuddyRequest(ui->edt_addBuddy->text());
       QMessageBox::information(this,"Add New Buddy", "Your request was sent for the user " + ui->edt_addBuddy->text(),QMessageBox::Ok);
       ui->edt_addBuddy->clear();
   }
}

void ColaborationWindow::on_create_channel_button_clicked()
{
    bool okCh;
    bool okPass;

    QString channelSelected = QInputDialog::getText(this,"Channel's Name","Channel name:",QLineEdit::Normal,0,&okCh);
    QString channelPass;
    if (okCh){
        if(!m_manager->channels().contains(channelSelected))
            channelPass = QInputDialog::getText(this,"password (Optionality)","Channel Pass:",QLineEdit::Normal,0,&okPass);
        else
            QMessageBox::information(this,"Invalid Name!", "The Channel you intented to create already exists.",QMessageBox::Ok);
    }
    if(!channelSelected.isEmpty() && okCh && okPass){
        this->m_manager->createChannel(channelSelected,channelPass);
        QTreeWidgetItem * channel_item = new QTreeWidgetItem(ui->channelView);
        channel_item->setText(0,channelSelected);
        channel_item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
        this->ui->l_channel_name->setText(channelSelected);
        this->ui->channelView->addTopLevelItem(channel_item);
        QTreeWidgetItem * users = new QTreeWidgetItem(channel_item);
        users->setFlags(!Qt::ItemIsSelectable);
        users->setText(0,this->m_manager->getLogin());
        this->setCurrentWidget(this->ui->t_channel);
        updateChannelsView();
    }
}

bool ColaborationWindow::loginIsInChannel(QTreeWidgetItem *channel){
    for(int i=0; i< channel->columnCount(); i++){
        if(channel->child(i)->text(0) == m_manager->getLogin() || channel->child(i)->text(0) == m_manager->getLogin() + "@gmail.com")
            return true;
        i++;
    }
    return false;
}

void ColaborationWindow::on_enter_button_clicked()
{
    int answer = QMessageBox::No;
    bool valid = false;
    if(this->ui->channelView->selectedItems().count() == 1){
        QString channelSelected = this->ui->channelView->currentItem()->text(0);
        QString atual_channel = m_manager->getChannel();

        //if the user is already in one channel, and the he is not in this channel
        if((!atual_channel.isEmpty()) && (!loginIsInChannel(ui->channelView->currentItem()))){
            answer = QMessageBox::question(this,"Change channel", "You already are in the channel: " + this->m_manager->getChannel() + " Do you wish to enter in the channel: " + channelSelected + " ?",QMessageBox::Yes, QMessageBox::No);
            if(answer == QMessageBox::Yes){
                valid = validateEnterChannel(channelSelected);
                if(valid)
                    setCurrentWidget(ui->t_channel);
            }
        }else{

            //if the channel selected is equals to the atual channel to forbide the enter in the channel
            if(!loginIsInChannel(ui->channelView->currentItem()))
                valid = validateEnterChannel(channelSelected);
            else{
                if(ui->l_channel_name->text().isEmpty())
                    QMessageBox::information(this,"Presence Detected!", "Your account is already in this channel.",QMessageBox::Ok);
                else
                    setCurrentWidget(ui->t_channel);
            }
        }
        //if the the enter the pass was acept or if the login is in the same channel execute this
        if(valid){
            if(ui->channelView->selectedItems().count() == 1){
                setCurrentWidget(ui->t_channel);
                this->ui->l_channel_name->setText(channelSelected);
                updateChannelsView();
            }
        }
    }
}

bool ColaborationWindow::validateEnterChannel(QString channelSelected){
    QString passInformed;
    bool valid;
    //if the channel is in the touche channels then if the channel has password solicite the password
    if(this->m_manager->channels().contains(channelSelected)){
        QString realPass_channel = this->m_manager->channels()[channelSelected]->password();
        //if the channel have pass solicite pass;
        if(!realPass_channel.isEmpty())
            passInformed = QInputDialog::getText(this,"Channel's Password","Channel Pass:",QLineEdit::Normal);

        //validate the password
        valid = this->m_manager->enterChannel(channelSelected,passInformed);
        if(valid){
            //if the user is not in channel, add him in channel
            if(this->ui->l_channel_name->text().isEmpty()){
                this->ui->l_channel_name->setText(channelSelected);
                addUserInChannelView(channelSelected);
            }
            //else remove him the anterior channel and add him in new channel
            else{
                addUserInChannelView(channelSelected);
                this->ui->l_channel_name->setText(channelSelected);
                updateChannelsView();
            }
        }
        else
            //only send message if the user informe the pass
            if(!passInformed.isEmpty())
                QMessageBox::information(this,"Invalid Password.", "The password informated is invalid",QMessageBox::Ok);
    }
    return valid;
}

void ColaborationWindow::addUserInChannelView(QString channelSelected){
    for(int i=0; i < ui->channelView->columnCount(); i++){
        QTreeWidgetItem *channel_item = this->ui->channelView->currentItem();
        if(this->ui->channelView->currentItem()->text(0) == channelSelected){
            QTreeWidgetItem * users = new QTreeWidgetItem(channel_item);
            users->setFlags(!Qt::ItemIsSelectable);
            users->setText(0,this->m_manager->getLogin());
            this->ui->channelView->currentItem()->addChild(users);
        }
    }
}
void ColaborationWindow::on_remove_buddy_clicked()
{
    if (ui->li_contactsList_2->selectedItems().count() == 1){
       int answer = QMessageBox::question(this,"Remove Buddy Request", "Are you sure about your request to remove the contact " + ui->li_contactsList_2->currentItem()->text()+ "?",QMessageBox::Yes, QMessageBox::No);
       if (answer == QMessageBox::Yes){
            emit buddyRemove(ui->li_contactsList_2->currentItem()->text());
            ui->li_contactsList_2->clear();
            ui->li_contactsList_2->addItems(m_manager->allBuddies());
        }
    }
}


void ColaborationWindow::on_b_startPrivateChat_clicked()
{
    if(ui->li_ContactsList->selectedItems().count() == 1){
        QString buddy(ui->li_ContactsList->selectedItems().first()->text());
        if(!buddies.contains(buddy)){
            TabWidget *newTab = new TabWidget(buddy, this);
            int rm_from = buddy.indexOf("@gmail.com");
            int len = buddy.length();
            QString bud = buddy;
            bud.remove(rm_from,len);
            buddies.insert(buddy, newTab);
            QTabWidget::addTab(newTab, bud);
            QTabWidget::setCurrentWidget(newTab);
            connect(newTab, SIGNAL(privateMessage(QString,QString)), this, SLOT(sendPrivateMessage(QString,QString)));
            connect(newTab, SIGNAL(destroyed(QObject*)), this, SLOT(onTabDeleted(QObject*)));
         }else{
            QTabWidget::setCurrentWidget(buddies[buddy]);
        }
    }
}

void ColaborationWindow::onTabDeleted(QObject *object)
{
    QString i(buddies.key(reinterpret_cast<TabWidget *>(object)));
    buddies.remove(i);
}

void ColaborationWindow::on_messageReceived(QXmppMessage m){
    if (buddies.contains(m.from())){
        int rm_from = m.from().indexOf("@gmail.com");
        int len = m.from().length();
        QString barejid = m.from().remove(rm_from,len);
        TabWidget *newTab = buddies.value(barejid + " wrote: " + m.body());
        int row = newTab->historico()->currentRow();
        newTab->historico()->addItem(m.body());
        newTab->historico()->setCurrentRow(++row);

    }
}

void ColaborationWindow::on_b_send_buddy_clicked(){
    QXmppMessage msg;
    this->m_manager->sendMessageToUser(msg);
}

void ColaborationWindow::on_b_send_channel_clicked()
{
    QString txtToChannel = ui->txt_chatChannel->toPlainText();
    QString channelSelected = ui->l_channel_name->text();
    int row = ui->li_channelChat->currentRow();
    if (!channelSelected.isEmpty() && !txtToChannel.isEmpty()){
        m_manager->sendMessageToChannel(channelSelected, Writer::writeText(txtToChannel));
        ui->li_channelChat->addItem(m_manager->getLogin() + " wrote: " + txtToChannel);
        ui->txt_chatChannel->clear();
        ui->li_channelChat->setCurrentRow(++row);
    }
}

void ColaborationWindow::on_txt_chatChannel_textChanged()
{
    if(ui->txt_chatChannel->document()->toPlainText().endsWith('\n')){
        on_b_send_channel_clicked();
    }
}
